{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VectorStoreRetrieverMemory\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`VectorStoreRetrieverMemory` 는 벡터 스토어에 메모리를 저장하고 호출될 때마다 가장 '눈에 띄는' 상위 K개의 문서를 쿼리합니다.\n",
    "\n",
    "이는 대화내용의 순서를 **명시적으로 추적하지 않는다는 점** 에서 다른 대부분의 메모리 클래스와 다릅니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# API KEY를 환경변수로 관리하기 위한 설정 파일\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# API KEY 정보로드\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "먼저, 벡터 스토어를 초기화 합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import faiss\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.docstore import InMemoryDocstore\n",
    "from langchain.vectorstores import FAISS\n",
    "\n",
    "\n",
    "# 임베딩 모델을 정의합니다.\n",
    "embeddings_model = OpenAIEmbeddings()\n",
    "\n",
    "# Vector Store 를 초기화 합니다.\n",
    "embedding_size = 1536\n",
    "index = faiss.IndexFlatL2(embedding_size)\n",
    "vectorstore = FAISS(embeddings_model, index, InMemoryDocstore({}), {})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "실제 사용에서는 `k`를 더 높은 값으로 설정하지만, 여기서는 `k=1` 을 사용하여 다음과 같이 표시합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.memory import VectorStoreRetrieverMemory\n",
    "\n",
    "# 벡터 조회가 여전히 의미적으로 관련성 있는 정보를 반환한다는 것을 보여주기 위해서입니다.\n",
    "retriever = vectorstore.as_retriever(search_kwargs={\"k\": 1})\n",
    "memory = VectorStoreRetrieverMemory(retriever=retriever)\n",
    "\n",
    "# 임의의 대화를 저장합니다.\n",
    "memory.save_context(\n",
    "    inputs={\n",
    "        \"human\": \"안녕하세요, 오늘 면접에 참석해주셔서 감사합니다. 자기소개 부탁드립니다.\"\n",
    "    },\n",
    "    outputs={\n",
    "        \"ai\": \"안녕하세요. 저는 컴퓨터 과학을 전공한 신입 개발자입니다. 대학에서는 주로 자바와 파이썬을 사용했으며, 최근에는 웹 개발 프로젝트에 참여하여 실제 사용자를 위한 서비스를 개발하는 경험을 했습니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"프로젝트에서 어떤 역할을 맡았나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"제가 맡은 역할은 백엔드 개발자였습니다. 사용자 데이터 처리와 서버 로직 개발을 담당했으며, RESTful API를 구현하여 프론트엔드와의 통신을 담당했습니다. 또한, 데이터베이스 설계에도 참여했습니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\n",
    "        \"human\": \"팀 프로젝트에서 어려움을 겪었던 경험이 있다면 어떻게 해결했나요?\"\n",
    "    },\n",
    "    outputs={\n",
    "        \"ai\": \"프로젝트 초기에 의사소통 문제로 몇 가지 어려움이 있었습니다. 이를 해결하기 위해 저희 팀은 정기적인 미팅을 갖고 각자의 진행 상황을 공유했습니다. 또한, 문제가 발생했을 때는 적극적으로 의견을 나누고, 합리적인 해결책을 찾기 위해 노력했습니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"개발자로서 자신의 강점은 무엇이라고 생각하나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"제 강점은 빠른 학습 능력과 문제 해결 능력입니다. 새로운 기술이나 도구를 빠르게 습득할 수 있으며, 복잡한 문제에 직면했을 때 창의적인 해결책을 제시할 수 있습니다. 또한, 팀워크를 중시하며 동료들과 협력하는 것을 중요하게 생각합니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "다음의 질문을 했을 때 Vector Store 로 부터 1개(k=1 이기 때문)의 가장 관련성 높은 대화를 반환합니다.\n",
    "\n",
    "- 질문: \"면접자 전공은 무엇인가요?\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 메모리에 질문을 통해 가장 연관성 높은 1개 대화를 추출합니다.\n",
    "print(memory.load_memory_variables({\"human\": \"면접자 전공은 무엇인가요?\"})[\"history\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "이번에는 다른 질문을 통해 가장 연관성 높은 1개 대화를 추출합니다.\n",
    "\n",
    "- 질문: \"면접자가 프로젝트에서 맡은 역할은 무엇인가요?\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\n",
    "    memory.load_memory_variables(\n",
    "        {\"human\": \"면접자가 프로젝트에서 맡은 역할은 무엇인가요?\"}\n",
    "    )[\"history\"]\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
